#!/bin/sh
set -e
echoerr() { printf "%s\n" "$*" >&2; }

#
# Read environment variables from file if envrionment variable ${1}_FILE is set
#
file_env() {
    local var=""
    local fileVar=""

    eval var="\$${1}"
    eval fileVar="\$${1}_FILE"

    local def="${2:-}"

    if [ -n "${var:-}" ] && [ -n "${fileVar:-}" ]; then
        echo >&2 "error: both ${1} and ${1}_FILE are set (but are exclusive)"
        exit 1
    fi

    local val="$def"

    if [ -n "${var:-}" ]; then
        val="${var}"
    elif [ -n "${fileVar:-}" ]; then
        val="$(cat "${fileVar}")"
    fi

    if [ -n "${val:-}" ]; then
        export "${1}"="$val"
    fi

    unset "${1}_FILE"
}

export SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}"
export SEMAPHORE_DB_PATH="${SEMAPHORE_DB_PATH:-/var/lib/semaphore}"
export SEMAPHORE_DB_PORT="${SEMAPHORE_DB_PORT:-}"

file_env 'SEMAPHORE_DB_USER'
file_env 'SEMAPHORE_DB_PASS'
file_env 'SEMAPHORE_ADMIN'
export SEMAPHORE_ADMIN_EMAIL="${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}"
export SEMAPHORE_ADMIN_NAME="${SEMAPHORE_ADMIN_NAME:-Semaphore Admin}"
file_env 'SEMAPHORE_ADMIN_PASSWORD'
export SEMAPHORE_LDAP_ACTIVATED="${SEMAPHORE_LDAP_ACTIVATED:-no}"
export SEMAPHORE_LDAP_HOST="${SEMAPHORE_LDAP_HOST:-}"
export SEMAPHORE_LDAP_PORT="${SEMAPHORE_LDAP_PORT:-}"
export SEMAPHORE_LDAP_DN_BIND="${SEMAPHORE_LDAP_DN_BIND:-}"
file_env 'SEMAPHORE_LDAP_PASSWORD'
export SEMAPHORE_LDAP_DN_SEARCH="${SEMAPHORE_LDAP_DN_SEARCH:-}"
export SEMAPHORE_LDAP_MAPPING_USERNAME="${SEMAPHORE_LDAP_MAPPING_USERNAME:-uid}"
export SEMAPHORE_LDAP_MAPPING_FULLNAME="${SEMAPHORE_LDAP_MAPPING_FULLNAME:-cn}"
export SEMAPHORE_LDAP_MAPPING_EMAIL="${SEMAPHORE_LDAP_MAPPING_EMAIL:-mail}"
file_env 'SEMAPHORE_ACCESS_KEY_ENCRYPTION'


[ -d "${SEMAPHORE_CONFIG_PATH}" ] || mkdir -p "${SEMAPHORE_CONFIG_PATH}" || {
    echo "Can't create Semaphore config path ${SEMAPHORE_CONFIG_PATH}."
    exit 1
}

[ -d "${SEMAPHORE_DB_PATH}" ] || mkdir -p "${SEMAPHORE_DB_PATH}" || {
    echo "Can't create Semaphore data path ${SEMAPHORE_DB_PATH}."
    exit 1
}


#
# Extract database host and port from config.json if they are not set.
# Set default SEMAPHORE_DB_DIALECT and SEMAPHORE_DB_HOST if empty.
#
if [ -z "${SEMAPHORE_DB_DIALECT}" ]; then
    if [ -f "${SEMAPHORE_CONFIG_PATH}/config.json" ]; then
        SEMAPHORE_DB_DIALECT=$(cat "${SEMAPHORE_CONFIG_PATH}/config.json" | jq '.dialect // ""' -r)
    fi
fi

export SEMAPHORE_DB_DIALECT="${SEMAPHORE_DB_DIALECT:-mysql}"

if [ -z "${SEMAPHORE_DB_HOST}" ]; then
    if [ -f "${SEMAPHORE_CONFIG_PATH}/config.json" ]; then
        SEMAPHORE_DB_HOST=$(cat "${SEMAPHORE_CONFIG_PATH}/config.json" | jq ".${SEMAPHORE_DB_DIALECT}.host // \"\"" -r)
    fi
fi

if [ -z "${SEMAPHORE_DB_HOST}" ]; then
    if [ "${SEMAPHORE_DB_DIALECT}" = 'bolt' ]; then
        export SEMAPHORE_DB_HOST=${SEMAPHORE_DB_PATH}/database.boltdb
    elif [ "${SEMAPHORE_DB_DIALECT}" = 'sqlite' ]; then
        export SEMAPHORE_DB_HOST=${SEMAPHORE_DB_PATH}/database.sqlite
    else
        export SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST:-0.0.0.0}"
    fi
fi


#
# Remove port number from SEMAPHORE_DB_HOST and put it to SEMAPHORE_DB_PORT
#
case "$SEMAPHORE_DB_HOST" in
  *:*)
    SEMAPHORE_DB_PORT=$(echo "$SEMAPHORE_DB_HOST" | cut -d ':' -f 2)
    SEMAPHORE_DB_HOST=$(echo "$SEMAPHORE_DB_HOST" | cut -d ':' -f 1)
    ;;
  *)
esac


#
# Set SEMAPHORE_DB_PORT if it is not set
#
if [ -z "${SEMAPHORE_DB_PORT}" ]; then
    case ${SEMAPHORE_DB_DIALECT} in
        mysql)
            SEMAPHORE_DB_PORT=3306
            ;;
        postgres)
            SEMAPHORE_DB_PORT=5432
            ;;
        bolt)
            ;;
        sqlite)
            ;;
        *)
            echoerr "Unknown database dialect: ${SEMAPHORE_DB_DIALECT}"
            exit 1
            ;;
    esac
fi


#
# Ping database if it is not BoltDB
#
if [ "${SEMAPHORE_DB_DIALECT}" != 'bolt' ] && [ "${SEMAPHORE_DB_DIALECT}" != 'sqlite' ]; then
    echoerr "Pinging database on ${SEMAPHORE_DB_HOST} port ${SEMAPHORE_DB_PORT}..."
    TIMEOUT=30


    while ! $(nc -z "$SEMAPHORE_DB_HOST" "$SEMAPHORE_DB_PORT") >/dev/null 2>&1; do
        TIMEOUT=$(expr $TIMEOUT - 1)

        if [ $TIMEOUT -eq 0 ]; then
            echoerr "Could not connect to database server. Exiting."
            exit 1
        fi

        echo -n "."
        sleep 1
    done
    
    export SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT}"
fi


#
# Generate new config.json if it does not exist
#
if [ ! -f "${SEMAPHORE_CONFIG_PATH}/config.json" ]; then
    echoerr "Generating setup file ${TMP_STDIN_CONFIG_FILE} ..."

    TMP_STDIN_CONFIG_FILE=$(mktemp)


    SEMAPHORE_TMP_PATH=${SEMAPHORE_TMP_PATH:-/tmp/semaphore}
    [ -d "${SEMAPHORE_TMP_PATH}" ] || mkdir -p "${SEMAPHORE_TMP_PATH}" || {
        echo "Can't create Semaphore tmp path ${SEMAPHORE_TMP_PATH}."
        exit 1
    }


    case ${SEMAPHORE_DB_DIALECT} in
        mysql)
            SEMAPHORE_DB_DIALECT_ID=1
            ;;
        bolt)
            SEMAPHORE_DB_DIALECT_ID=2
            ;;
        postgres)
            SEMAPHORE_DB_DIALECT_ID=3
            ;;
        sqlite)
            SEMAPHORE_DB_DIALECT_ID=4
            ;;
        *)
            echoerr "Unknown database dialect: ${SEMAPHORE_DB_DIALECT}"
            exit 1
            ;;
    esac


    cat << EOF > "${TMP_STDIN_CONFIG_FILE}"
${SEMAPHORE_DB_DIALECT_ID}
EOF

    if [ "${SEMAPHORE_DB_DIALECT}" = "bolt" ]; then
        cat << EOF >> "${TMP_STDIN_CONFIG_FILE}"
${SEMAPHORE_DB_HOST}
EOF
    elif [ "${SEMAPHORE_DB_DIALECT}" = "sqlite" ]; then
        cat << EOF >> "${TMP_STDIN_CONFIG_FILE}"
${SEMAPHORE_DB_HOST}
EOF
    else
        cat << EOF >> "${TMP_STDIN_CONFIG_FILE}"
${SEMAPHORE_DB_HOST}
${SEMAPHORE_DB_USER}
${SEMAPHORE_DB_PASS}
${SEMAPHORE_DB:-semaphore}
EOF
    fi

    cat << EOF >> "${TMP_STDIN_CONFIG_FILE}"
${SEMAPHORE_TMP_PATH}
${SEMAPHORE_WEB_ROOT:-}
no
no
no
no
no
${SEMAPHORE_LDAP_ACTIVATED}
EOF

    if [ "${SEMAPHORE_LDAP_ACTIVATED}" = "yes" ]; then
        cat << EOF >> "${TMP_STDIN_CONFIG_FILE}"
${SEMAPHORE_LDAP_HOST}:${SEMAPHORE_LDAP_PORT}
${SEMAPHORE_LDAP_NEEDTLS:-no}
${SEMAPHORE_LDAP_DN_BIND}
${SEMAPHORE_LDAP_PASSWORD}
${SEMAPHORE_LDAP_DN_SEARCH}
${SEMAPHORE_LDAP_SEARCH_FILTER:-(uid=%s)}
${SEMAPHORE_LDAP_MAPPING_DN:-dn}
${SEMAPHORE_LDAP_MAPPING_USERNAME}
${SEMAPHORE_LDAP_MAPPING_FULLNAME}
${SEMAPHORE_LDAP_MAPPING_EMAIL}
EOF
    fi;

    cat << EOF >> "${TMP_STDIN_CONFIG_FILE}"
${SEMAPHORE_CONFIG_PATH}
${SEMAPHORE_ADMIN}
${SEMAPHORE_ADMIN_EMAIL}
${SEMAPHORE_ADMIN_NAME}
${SEMAPHORE_ADMIN_PASSWORD}
EOF


    echoerr "Executing semaphore setup"
    if test "$#" -ne 1; then
        /usr/local/bin/semaphore setup - < "${TMP_STDIN_CONFIG_FILE}"
    else
        "$1" setup - < "${TMP_STDIN_CONFIG_FILE}"
    fi

    rm -f "${TMP_STDIN_CONFIG_FILE}"
fi


#
# Install additional python dependencies
#
if test -f "${SEMAPHORE_CONFIG_PATH}/requirements.txt"; then
    echoerr "Installing additional python dependencies"
    pip3 install --upgrade \
        -r "${SEMAPHORE_CONFIG_PATH}/requirements.txt"
else
    echoerr "No additional python dependencies to install"
fi


# Import project if environment variable SEMAPHORE_IMPORT_PROJECT_FILE is defined.
if [ -n "${SEMAPHORE_IMPORT_PROJECT_FILE:-}" ]; then
    echoerr "Importing project from ${SEMAPHORE_IMPORT_PROJECT_FILE}"
    if test "$#" -ne 1; then
        /usr/local/bin/semaphore project import --file "${SEMAPHORE_IMPORT_PROJECT_FILE}" || echoerr "Project import failed"
    else
        "$1" project import --file "${SEMAPHORE_IMPORT_PROJECT_FILE}" || echoerr "Project import failed"
    fi
fi


#
# Start Semaphore server
#
echoerr "Starting semaphore server"
if test "$#" -ne 1; then
    exec /usr/local/bin/semaphore server --config "${SEMAPHORE_CONFIG_PATH}/config.json"
else
    exec "$@"
fi
